﻿using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using VisionCloud.Core;

namespace VisionCloud.Domain.UnitOfWork
{
    public class PGUnitOfWork : IUnitOfWork
    {
        public BlueDbContext Db { get; set; }

        public async Task ExecuteAsync(Func<Task> action)
        {
            // Use of an EF Core resiliency strategy when using multiple DbContexts
            // within an explicit BeginTransaction():
            // https://docs.microsoft.com/ef/core/miscellaneous/connection-resiliency
            var strategy = Db.Database.CreateExecutionStrategy();
            await strategy.ExecuteAsync(async () =>
            {
                using (var transaction = Db.Database.BeginTransaction())
                {
                    await action();
                    transaction.Commit();
                }
            }).ConfigureAwait(false);
        }

        public async Task OpenTrans(Func<Func<Task<int>>, Task> action)
        {
            var strategy = Db.Database.CreateExecutionStrategy();
            await strategy.ExecuteAsync(async () =>
            {
                using (var tran = Db.Database.BeginTransaction())
                {
                    try
                    {
                        await action(async () => await Db.SaveChangesAsync());
                        await Db.SaveChangesAsync();
                        tran.Commit();
                    }
                    catch (Exception ex)
                    {
                        tran.Rollback();
                        throw ex;
                    }
                }
            }).ConfigureAwait(false);
        }

        public async Task<T> OpenTrans<T>(Func<Func<Task<int>>, Task<T>> func)
        {
            using (var tran = Db.Database.BeginTransaction())
            {
                try
                {
                    var result = await func(async () => await Db.SaveChangesAsync());
                    await Db.SaveChangesAsync();
                    tran.Commit();
                    return result;
                }
                catch
                {
                    tran.Rollback();
                    throw;
                }
            }
        }

        public void Reset()
        {
            var entities = Db.ChangeTracker.Entries().ToList();
            for (int i = 0, max = entities.Count(); i < max; i++)
            {
                entities[i].State = EntityState.Detached;
            }
        }

        /// <summary>
        /// 事务提交
        /// </summary>
        /// <returns></returns>
        public Task<int> SaveChangesAsync()
        {
            return Db.SaveChangesAsync();
        }

        /// <summary>
        /// 事务提交
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public Task<int> SaveChangesAsync(CancellationToken cancellationToken)
        {
            return Db.SaveChangesAsync(cancellationToken);
        }

        //public void Dispose()
        //{
        //    //Debug.WriteLine($" {this.GetType().Name} db销毁了");
        //    //if (Db != null)
        //    //{
        //    //    Db.Dispose();
        //    //}
        //}
    }
}